/**
 * 
 */
package com.google.code.jkippt;

import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;

import com.google.code.jkippt.annotation.Experimental;
import com.google.code.jkippt.http.APIClient;
import com.google.code.jkippt.http.ResourceEndpointUrlFactory;
import com.google.code.jkippt.parser.Parser;
import com.google.code.jkippt.query.ClipQuery;
import com.google.code.jkippt.resource.Clip;
import com.google.code.jkippt.resource.ClipList;
import com.google.code.jkippt.resource.User;

/**
 * @author "Federico De Faveri defaveri@gmail.com"
 *
 */
public class Lists extends KipptEndpoint {
	
	public static final String LIST_ENDPOINT_NAME = "lists";
	
	protected static final String CLIPS = "clips";
	protected static final String RELATIONSHIP = "relationship";
	protected static final String FOLLOW_ACTION = "{\"action\": \"follow\"}";
	protected static final String UNFOLLOW_ACTION = "{\"action\": \"unfollow\"}";
	
	protected ResourceEndpoint<ClipList> listEndpoint;
	protected ResourceEndpoint<Clip> clipEndpoint;
	
	
	protected Lists(APIClient client, Parser parser) {
		super(client, parser, LIST_ENDPOINT_NAME);
		listEndpoint = new ResourceEndpoint<ClipList>(client, parser, endpointUrlFactory, ClipList.class);
		clipEndpoint = new ResourceEndpoint<Clip>(client, parser, endpointUrlFactory, Clip.class);
	}
	
	/**
	 * Retrieves all available List.
	 * @return an {@link Iterator} over the {@link ClipList} set.
	 * @throws JKipptException if an error occurs.
	 */
	public Iterator<ClipList> getAll() throws JKipptException
	{
		return listEndpoint.getAll();
	}

	/**
	 * Returns the specified {@link ClipList}.
	 * @param id the list id.
	 * @return the retrieved {@link ClipList}.
	 * @throws JKipptException if an error occurs.
	 */
	public ClipList get(String id) throws JKipptException
	{
		return listEndpoint.get(id);
	}
	
	/**
	 * Gets the {@link Clip}s belongin to the specified {@link ClipList}.
	 * @param id the {@link ClipList} id.
	 * @return the retrieved {@link Clip}s.
	 * @throws JKipptException if an error occurs.
	 */
	public Iterator<Clip> getClips(String id) throws JKipptException
	{
		String firstPageEnpoint = endpointUrlFactory.buildEndpointUrl(Arrays.asList(id, CLIPS), ResourceEndpointUrlFactory.NO_PARAMETERS);
		return clipEndpoint.getPaginated(firstPageEnpoint); 
	}
	
	/**
	 * Gets the {@link Clip}s belongin to the specified {@link ClipList}.
	 * @param id the {@link ClipList} id.
	 * @param query the retrieving parameters.
	 * @return the retrieved {@link Clip}s.
	 * @throws JKipptException if an error occurs.
	 */
	public Iterator<Clip> getClips(String id, ClipQuery query) throws JKipptException
	{
		Map<String, String> parameters = query.toParameters();
		String firstPageEnpoint = endpointUrlFactory.buildEndpointUrl(Arrays.asList(id, CLIPS), parameters);
		return clipEndpoint.getPaginated(firstPageEnpoint); 
	}
	
	/**
	 * Gets information about a relationship to a list.
	 * @param id the {@link ClipList} id.
	 * @return <code>true</code> if there is a relationship, <code>false</code> otherwise.
	 * @throws JKipptException if an error occurs retrieving {@link User} relationship.
	 */
	public boolean getRelationship(String id) throws JKipptException
	{
		String endpoint = endpointUrlFactory.buildEndpointUrl(id, RELATIONSHIP);
		String json = client.get(endpoint);
		return parser.parseRelationship(json);
	}
	
	/**
	 * Updates the given list.
	 * @param list the {@link ClipList} to update.
	 * @return the updated {@link ClipList}.
	 * @throws JKipptException if an error occurs.
	 */
	public ClipList update(ClipList list) throws JKipptException
	{
		return listEndpoint.update(list);
	}
	
	/**
	 * Adds a new {@link ClipList}.
	 * @param title the list title.
	 * @return the created {@link ClipList}.
	 * @throws JKipptException if an error occurs.
	 */
	public ClipList add(String title) throws JKipptException
	{
		ClipList list = new ClipList(title);
		return listEndpoint.add(list);
	}
	
	/**
	 * Adds a new {@link ClipList}.
	 * @param title the list title.
	 * @param description the list description.
	 * @return the created {@link ClipList}.
	 * @throws JKipptException if an error occurs.
	 */
	@Experimental
	public ClipList add(String title, String description) throws JKipptException
	{
		ClipList list = new ClipList(title, description);
		return listEndpoint.add(list);
	}
	
	/**
	 * Make the user following the specified {@link ClipList}.
	 * @param id the id of the {@link ClipList} to follow.
	 * @return the updated status.
	 * @throws JKipptException if an error occurs during the relationship update.
	 */
	public boolean follow(String id) throws JKipptException
	{
		String endpoint = endpointUrlFactory.buildEndpointUrl(id, RELATIONSHIP);

		String json = client.post(endpoint, FOLLOW_ACTION);
		return parser.parseRelationship(json);
	}

	/**
	 * Make the user unfollowing the specified {@link ClipList}.
	 * @param id the id of the {@link ClipList} to unfollow.
	 * @return the updated status.
	 * @throws JKipptException if an error occurs during the relationship update.
	 */
	public boolean unfollow(String id) throws JKipptException
	{
		String endpoint = endpointUrlFactory.buildEndpointUrl(id, RELATIONSHIP);
		String json = client.post(endpoint, UNFOLLOW_ACTION);
		return parser.parseRelationship(json);
	}

	/**
	 * Deletes the specified {@link ClipList}.
	 * @param id the List id to remove.
	 * @throws JKipptException if an error occurs.
	 */
	public void delete(String id) throws JKipptException
	{
		listEndpoint.delete(id);
	}

}
